parser grammar YACCParser;

options {
  language = Java;
  tokenVocab = YACCLexer;
  backtrack = true;
}

@header {
  package practica7;
}

@members {

     private ArrayList<RecognitionException> errors = new ArrayList<RecognitionException>();
     public ArrayList<RecognitionException> getErrors() {
        return errors;
     }
     @Override
     public void reportError (RecognitionException e) {
        String msg = getErrorMessage(e, getTokenNames());
        System.err.println(msg);
        errors.add(e);
     }
}




entrada: primerbloque? segundobloque tercerbloque?;


/////////////////
//PRIMER BLOQUE//
/////////////////
primerbloque: declaraciones;
  declaraciones: seccion declaracionvar*;
    seccion: PORCENTAJE LLAVE_A (incluir|record|defvar)* PORCENTAJE LLAVE_C;
      incluir: ALMOHADILLA INCLUIR var_ang;
      record: TIPODEF RECORD IDENT cuerpodeclaracion;
        cuerpodeclaracion: LLAVE_A defvar* LLAVE_C (INTERVALO PUNTO_COMA)?;
      defvar: tipo ASTERISCO? (IDENT|ident_vector) (PARENTESIS_A PARENTESIS_C)?  (IGUAL (NUMERO|IDENT))? (COMA ASTERISCO? (IDENT|ident_vector) (PARENTESIS_A PARENTESIS_C)?  (IGUAL (NUMERO|IDENT))?)* PUNTO_COMA;
    declaracionvar: reservadas ((cuerpodeclaracion)|((IDENT|SIMBOLO|var_ang) (IDENT|SIMBOLO)*));
      reservadas: START|UNION|TOKEN|TYPE|LEFT|RIGHT|NONASSOC;
    


//////////////////
//SEGUNDO BLOQUE//
//////////////////
segundobloque: NUEVOBLOQUE reglas*;
  reglas: nombreregla DOS_PUNTOS cuerporegla PUNTO_COMA;
    nombreregla: IDENT;
    cuerporegla: dentrocuerpo? (OR dentrocuerpo)*;
      dentrocuerpo: SIMBOLO? (IDENT PORCENTAJE? SIMBOLO?)+ accion?;
        accion: LLAVE_A (regla_if|imprimir|(asignacion PUNTO_COMA)|(IDENT PUNTO_COMA))+ LLAVE_C;
          imprimir: PRINTF PARENTESIS_A CADENA (COMA VALOR)* PARENTESIS_C PUNTO_COMA;
          asignacion: ASTERISCO? (IDENT|ident_vector|PSEUDOVAR) (COMA (IDENT|ident_vector|PSEUDOVAR))* IGUAL GUION? resultadoasig;
            resultadoasig: (IDENT|SIMBOLO|NUMERO|VALOR|ident_vector|operacion|asignacion|llamada_funcion);
            ident_vector: IDENT corchetes;
              corchetes: CORCHETE_A (VALOR|NUMERO|operacion)? CORCHETE_C;
            operacion: (VALOR|IDENT|NUMERO) operador (IDENT|VALOR|SIMBOLO|NUMERO);
              operador: SUMA|GUION|ASTERISCO|SLASH;




/////////////////
//TERCER BLOQUE//
/////////////////
tercerbloque: NUEVOBLOQUE programas;
  programas: definir funciones funcionyacc*;
    definir: ALMOHADILLA DEFINIR IDENT NUMERO;
    funciones: tipo? IDENT PARENTESIS_A parametros PARENTESIS_C cuerpo;
      parametros: ((VOID)? | tipo parametro (COMA tipo parametro)*);
        parametro: (ASTERISCO? IDENT CORCHETES*) | CADENA | NUMERO;
      cuerpo: (LLAVE_A instrucciones* LLAVE_C)|instrucciones;
        instrucciones: ((retorno|llamada_funcion PUNTO_COMA)|salir|continuar|defvar|regla_while|regla_if|regla_for|imprimir|(asignacion PUNTO_COMA)|(IDENT PUNTO_COMA));
        retorno: RET ((PARENTESIS_A (IDENT|NUMERO|SIMBOLO|llamada_funcion) PARENTESIS_C)|((IDENT|NUMERO|SIMBOLO|llamada_funcion))) PUNTO_COMA;


regla_while: WHILE condicion cuerpo;
  condicion: NOT? PARENTESIS_A comparacion ((COND_AND|COND_OR) NOT? comparacion)* PARENTESIS_C;
    comparacion: opcionescomparacion (comparador opcionescomparacion)*;
      opcionescomparacion: (expr|llamada_funcion|NUMERO|IDENT|PSEUDOVAR|SIMBOLO|incremento|decremento);
      expr: PARENTESIS_A (asignacion|operacion) PARENTESIS_C;


regla_if: IF condicion cuerpo (ELSE cuerpo)?;

    
regla_for: FOR PARENTESIS_A iteracion_for PARENTESIS_C cuerpo;
  iteracion_for: ((INT? asignacion)|PUNTO_COMA) comparacion? PUNTO_COMA (incremento|decremento)? (COMA asignacion)?;
    incremento: (PARENTESIS_A? IDENT PARENTESIS_C? INCREMENTO)|(PARENTESIS_A? INCREMENTO IDENT PARENTESIS_C?)|
                (IDENT INCREMENTO)|(INCREMENTO IDENT);
    decremento: (PARENTESIS_A? IDENT PARENTESIS_C? DECREMENTO)|(PARENTESIS_A? DECREMENTO IDENT PARENTESIS_C?)|
                (IDENT DECREMENTO)|(DECREMENTO IDENT);
    
    
funcionyacc: INTERVALO? llamada_funcion defvar* cuerpo;

llamada_funcion: IDENT PARENTESIS_A ((VALOR|IDENT|NUMERO|operacion) (COMA (VALOR|IDENT|NUMERO|operacion))*)? PARENTESIS_C;
tipo: DOBLE|INT|CHAR|VOID|INTERVALO|REGISTRO;
comparador: IGUALQUE|MAYORQUE|MENORQUE|MAYORIGUALQUE|MENORIGUALQUE;
var_ang: MENORQUE IDENT MAYORQUE;
continuar: CONTINUE PUNTO_COMA;
salir: BREAK PUNTO_COMA;